﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using SSSGame.Physics;
using Microsoft.Xna.Framework.Graphics;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using System.IO;

namespace SSSGame
{
    public class Player
    {
        public KeyboardState _lastPlayerState;
        public Ship _PlayerShip;
        public PlayerContentManager _playerContentManager;
        public Vector2 _NouveauVecteurReel = new Vector2();

        private bool _initializationMade = false;
        private List<Vector2> _starsList = new List<Vector2>();
        private List<Vector2> _parcours;

        private int loopCounter = 0;
        private double fps = 0;
        private double showedFPS = 0;

        private float _scale = 1f;

        public Player(SSS sssGame)
        {
            _PlayerShip = new Ship();        
            _playerContentManager = new PlayerContentManager(sssGame);
            _PlayerShip._VecteurPosition = new Vector2(_playerContentManager._graphics.PreferredBackBufferWidth / 2, _playerContentManager._graphics.PreferredBackBufferHeight / 2);
        }

        public int UpdatePlayer(GameTime gameTime)
        {
            if (loopCounter < 50)
            {
                fps += gameTime.ElapsedGameTime.TotalMilliseconds;
                loopCounter++;
            }
            else
            {
                showedFPS = 50 / (fps / 1000);
                loopCounter = 0;
                fps = 0;
            }

            // Gestion des animations
            _playerContentManager._tagAnimation.GetAnimation(gameTime);

            // Gestion de la rotation du vaisseau
            if (!CalculRotation(gameTime))
            {
                // Gestion de la translation
                if (CalculTranslation(gameTime) != Tools.QUITTER)
                {
                    // Scrolling uniforme et permanent : le vaisseau reste au centre de l'écran
                    _playerContentManager._offSet = _PlayerShip._VecteurVitesseLineaire.DonnerNouvellePosition(_PlayerShip._VecteurPosition, 2) - _PlayerShip._VecteurPosition;

                    // Définition du vecteur avec un coefficient de dilatation des valeurs (<1) ou au contraire écrasement (>1)
                    _NouveauVecteurReel = _PlayerShip._VecteurVitesseLineaire.DonnerNouvellePosition(_PlayerShip._VecteurPosition, 3);
                }
                else
                    return Tools.QUITTER;
            }
            return 0;
        }

        public void DrawPlayer()
        {
            string uniteVitesse = "m/s";
            string valeurVitesse = _PlayerShip._VecteurVitesseLineaire.DonnerNorme().ToString();
            if (_PlayerShip._VecteurVitesseLineaire.DonnerNorme() > 1000)
            {
                uniteVitesse = "km/s";
                valeurVitesse = (_PlayerShip._VecteurVitesseLineaire.DonnerNorme() / 1000).ToString();
            }
            string text1 = string.Format("Vitesse lineaire : {0} {1}", valeurVitesse, uniteVitesse);
            string text2 = string.Format("Beta vitesse lineaire : {0} {1}", MathExtensions.RadToDegrees(_PlayerShip._VecteurVitesseLineaire.DonnerBetaVecteur()), "deg");
            string text3 = string.Format("Omega vitesse angulaire : {0} {1}", MathExtensions.RadToDegrees(_PlayerShip._VecteurVitesseAngulaire.DonnerOmega()), "deg");
            string text4 = string.Format("FPS : {0}", showedFPS);
            string text5 = string.Format("Nombre d'etoiles affichees : {0}", _starsList.Count);

            _playerContentManager._spriteBatch.Begin();

            if (!_initializationMade)
            {
                GenererBackGround();
                //GenererParcours();
            }

            AfficherBackGround(_playerContentManager._offSet);
            //AfficherParcours(_playerContentManager._offSet);

            //_scale = DonnerScaleVaisseau();

            _playerContentManager._spriteBatch.Draw(_PlayerShip._activeShipSprite,                                  // Texture (Image)
                 _PlayerShip._VecteurPosition,                                                                      // Position de l'image
                 null,                                                                                              // Zone de l'image à afficher
                 Color.White,                                                                                       // Teinte
                 _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(),                                                // Rotation (en rad)
                 new Vector2(_PlayerShip._activeShipSprite.Width / 2, _PlayerShip._activeShipSprite.Height / 2),    // Origine
                 _scale,                                                                                            // Echelle
                 SpriteEffects.None,                                                                                // Effet
                 0);                                                                                                // Profondeur                                      

            _playerContentManager._spriteBatch.DrawString(_playerContentManager._police, text1, Vector2.Zero, Color.White);
            _playerContentManager._spriteBatch.DrawString(_playerContentManager._police, text2, new Vector2(0, 15), Color.White);
            _playerContentManager._spriteBatch.DrawString(_playerContentManager._police, text3, new Vector2(0, 30), Color.White);
            _playerContentManager._spriteBatch.DrawString(_playerContentManager._police, text4, new Vector2(0, 45), Color.Red);
            _playerContentManager._spriteBatch.DrawString(_playerContentManager._police, text5, new Vector2(0, 60), Color.Red);

            // Gestion des flèches d'orientation

            // Orientation vecteur rotation
            _playerContentManager._spriteBatch.Draw(_playerContentManager._orientation_ship,                              // Texture (Image)
                new Vector2(500,500),                                                                               // Position de l'image
                 null,                                                                                              // Zone de l'image à afficher
                 Color.White,                                                                                       // Teinte
                 _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(),                                                // Rotation (en rad)
                 new Vector2(0, _playerContentManager._orientation_ship.Height / 2),    // Origine
                 _scale,                                                                                            // Echelle
                 SpriteEffects.None,                                                                                // Effet
                 0);                                                                                              // Profondeur    

            // Orientation vecteur translation
            _playerContentManager._spriteBatch.Draw(_playerContentManager._orientation_poussee,                              // Texture (Image)
                new Vector2(500, 500),                                                                               // Position de l'image
                 null,                                                                                              // Zone de l'image à afficher
                 Color.White,                                                                                       // Teinte
                 _PlayerShip._VecteurVitesseLineaire.DonnerBetaVecteur(),                                                // Rotation (en rad)
                 new Vector2(0, _playerContentManager._orientation_poussee.Height / 2),    // Origine
                 _scale,                                                                                            // Echelle
                 SpriteEffects.None,                                                                                // Effet
                 0);   

            _playerContentManager._spriteBatch.End();
        }

        private float DonnerScaleVaisseau()
        {
            float result = _scale;

            // tant que le vaisseau accélère, on diminue le scale
            if (_PlayerShip._VecteurVitesseLineaire.DonnerNorme() > 10 && _scale >= 0.01f)
                result -= 0.0005f;
            else if (_PlayerShip._VecteurVitesseLineaire.DonnerNorme() <= 10 && _scale <= 1.0f)
                result += 0.0005f;

            return result;
        }

        private bool CalculRotation(GameTime gameTime)
        {
            switch (DetectionMouvementRotation())
            {
                case Tools.ROTATION_HORAIRE_ACTIVE:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._shipRotationHoraire;

                        _PlayerShip._VecteurVitesseAngulaire = VecteurVitesseAngulaire.DonnerNouveauVecteurVitesseAngulaire(
                                Tools.ORIENTATION_HORAIRE,
                                (float)Convert.ToDouble(gameTime.ElapsedGameTime.Milliseconds) / 1000,
                                _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(),
                                MathExtensions.PI);

                        return true;
                    }

                case Tools.ROTATION_RETROGRADE_ACTIVE:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._shipRotationRetrograde;

                        _PlayerShip._VecteurVitesseAngulaire = VecteurVitesseAngulaire.DonnerNouveauVecteurVitesseAngulaire(
                        Tools.ORIENTATION_RETROGRADE,
                        (float)Convert.ToDouble(gameTime.ElapsedGameTime.Milliseconds) / 1000,
                        _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(),
                        MathExtensions.PI);

                        return true;
                    }
                default:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._ship;
                        _PlayerShip._VecteurVitesseAngulaire = new VecteurVitesseAngulaire(_PlayerShip._VecteurVitesseAngulaire.DonnerOrientationVecteur(),
                            _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(), 0f);

                        return false;
                    }
            }
        }

        private int CalculTranslation(GameTime gameTime)
        {
            switch (DectionMouvementLineaire())
            {
                case Tools.QUITTER:
                    return Tools.QUITTER;

                case Tools.PROPULSTION_ACTIVE:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._shipBoost_main;

                        if (_playerContentManager._propulseurSoundInstance.State != SoundState.Playing)
                            _playerContentManager._propulseurSoundInstance.Play();

                        _PlayerShip._VecteurVitesseLineaire = VecteurVitesseLineaire.DonnerNouveauVecteurVitesseLineaire(
                            _PlayerShip._shipLinearAcceleration, // rapport force / masse (N / kg)
                            Convert.ToDouble(gameTime.ElapsedGameTime.Milliseconds) / 1000,  // temps écoulé
                            _PlayerShip._VecteurVitesseLineaire.DonnerNorme(),  // vitesse initiale (m/s)
                            _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(), // angle formé par le vecteur accélération / abscisse
                            _PlayerShip._VecteurVitesseLineaire.DonnerBetaVecteur()); // angle formé par le vecteur vitesse initiale / abscisse
                        break;
                    }

                case Tools.RETROPROPULSTION_ACTIVE:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._shipBoost_retro;

                        _PlayerShip._VecteurVitesseLineaire = (VecteurVitesseLineaire.DonnerNouveauVecteurVitesseLineaire(
                            _PlayerShip._shipLinearAcceleration, // rapport force / masse (N / kg)
                            Convert.ToDouble(gameTime.ElapsedGameTime.Milliseconds) / 1000,  // temps écoulé
                            _PlayerShip._VecteurVitesseLineaire.DonnerNorme(),  // vitesse initiale (m/s)
                            _PlayerShip._VecteurVitesseAngulaire.DonnerOmega() - (Math.PI), // angle formé par le vecteur accélération / abscisse
                            _PlayerShip._VecteurVitesseLineaire.DonnerBetaVecteur())); // angle formé par le vecteur vitesse initiale / abscisse

                        break;
                    }

                default:
                    {
                        _PlayerShip._activeShipSprite = _playerContentManager._ship;

                        if (_playerContentManager._propulseurSoundInstance.State == SoundState.Playing)
                            _playerContentManager._propulseurSoundInstance.Stop();

                        _PlayerShip._VecteurVitesseLineaire = (VecteurVitesseLineaire.DonnerNouveauVecteurVitesseLineaire(
                            0f, // rapport force / masse (N / kg)
                            Convert.ToDouble(gameTime.ElapsedGameTime.Milliseconds) / 1000,  // temps écoulé
                            _PlayerShip._VecteurVitesseLineaire.DonnerNorme(),  // vitesse initiale (m/s)
                            _PlayerShip._VecteurVitesseAngulaire.DonnerOmega(), // angle formé par le vecteur accélération / abscisse
                            _PlayerShip._VecteurVitesseLineaire.DonnerBetaVecteur())); // angle formé par le vecteur vitesse initiale / abscisse

                        break;
                    }
            }
            return 0;
        }
        
        private int DectionMouvementLineaire()
        {
            _lastPlayerState = Keyboard.GetState();

            if (_lastPlayerState.IsKeyDown(Keys.Escape))
            {
                return Tools.QUITTER;
            }

            // Propulsion principale
            if (_lastPlayerState.IsKeyDown(Keys.Up))
            {
                return Tools.PROPULSTION_ACTIVE;
            }

            // Retro-propulsion
            if (_lastPlayerState.IsKeyDown(Keys.Down))
            {
                return Tools.RETROPROPULSTION_ACTIVE;
            }

            return 0;
        }

        private int DetectionMouvementRotation()
        {
            _lastPlayerState = Keyboard.GetState();
            
            // Rotation horaire
            if (_lastPlayerState.IsKeyDown(Keys.Right))
            {
                return Tools.ROTATION_HORAIRE_ACTIVE;
            }

            // Rotation retrograde
            if (_lastPlayerState.IsKeyDown(Keys.Left))
            {
                return Tools.ROTATION_RETROGRADE_ACTIVE;
            }

            return 0;
        }

        private void GenererBackGround()
        {
            Random nb = new Random();
            for (int i = -8000; i < 8000; i += 20)
            {
                for (int j = -8000; j < 8000; j += 20)
                {
                    if (nb.Next(5) == 1)
                        _starsList.Add(new Vector2(i, j));
                }
            }
            _initializationMade = true;
        }

        private void GenererParcours()
        {
            _parcours = new List<Vector2>();
            
            // Première ligne droite
            for (int i = 100; i <= 2000; i += 100)
            {
                _parcours.Add(new Vector2(i, 300));
                _parcours.Add(new Vector2(i, 500));
            }

            // Premier virage à droite

            for (int i = 1910; i <= 1990; i += 10)
            {
                _parcours.Add(new Vector2(i, 500));
                _parcours.Add(new Vector2(i, 700));
            }

            for (int i = 510; i <= 690; i += 10)
            {
                _parcours.Add(new Vector2(2000, i));
            }

            for (int i = 300; i <= 900; i += 10)
            {
                _parcours.Add(new Vector2(2100, i));
            }

            _parcours.Add(new Vector2(2000, 700));
            _parcours.Add(new Vector2(1900, 700));

            _parcours.Add(new Vector2(2000, 900));
            _parcours.Add(new Vector2(1900, 900));
        }

        private void AfficherBackGround(Vector2 offSet)
        {
            for (int i = 0; i < _starsList.Count; i++)
            {
                _starsList[i] -= offSet;
                _playerContentManager._spriteBatch.Draw(_playerContentManager._star, _starsList[i], Color.White);
            }
        }

        private void AfficherParcours(Vector2 offSet)
        {
            for (int i = 0; i < _parcours.Count; i++)
            {
                _parcours[i] -= offSet;
                _playerContentManager._spriteBatch.Draw(_playerContentManager._balise3,
                     _parcours[i],
                     null,
                     _playerContentManager._tagAnimation.GetTagColor(),
                     0,
                     new Vector2(0, 0),
                     _playerContentManager._tagAnimation.GetScale(),
                     SpriteEffects.None,
                     0);  
            }
        }
    }
}
